﻿using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using System.Windows.Forms;

using Timer = System.Windows.Forms.Timer;

namespace YGBookmark.Services
{
    /// <summary>
    /// 剪贴板监控服务（使用Windows消息循环实现高效监听）
    /// </summary>
    public class ClipboardMonitor : IDisposable
    {
        #region Win32 API声明
        private const int WM_CLIPBOARDUPDATE = 0x031D;
        private const int CW_USEDEFAULT = unchecked((int)0x80000000);

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool AddClipboardFormatListener(IntPtr hwnd);

        [DllImport("user32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        private static extern bool RemoveClipboardFormatListener(IntPtr hwnd);

        [DllImport("user32.dll")]
        private static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
        #endregion

        #region 事件定义
        /// <summary>
        /// 当检测到有效URL时触发
        /// </summary>
        public event EventHandler<string> UrlDetected;
        #endregion

        #region 私有成员
        private readonly ClipboardListenerWindow _listenerWindow;
        private readonly Timer _debounceTimer;
        private string _lastContent = string.Empty;
        private bool _isProcessing;
        private static readonly Regex _urlRegex = new Regex(
            @"^(https?|ftp)://[^\s/$.?#].[^\s]*$",
            RegexOptions.IgnoreCase | RegexOptions.Compiled);
        #endregion

        /// <summary>
        /// 初始化剪贴板监控服务
        /// </summary>
        public ClipboardMonitor()
        {
            _listenerWindow = new ClipboardListenerWindow();
            _listenerWindow.ClipboardUpdated += OnClipboardUpdated;

            _debounceTimer = new Timer { Interval = 500 };
            _debounceTimer.Tick += (s, e) => _isProcessing = false;
        }

        /// <summary>
        /// 启动监控
        /// </summary>
        public void Start()
        {
            if (!AddClipboardFormatListener(_listenerWindow.Handle))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }
        }

        /// <summary>
        /// 停止监控
        /// </summary>
        public void Stop()
        {
            RemoveClipboardFormatListener(_listenerWindow.Handle);
        }

        #region 事件处理
        private void OnClipboardUpdated(object sender, EventArgs e)
        {
            if (_isProcessing) return;

            _isProcessing = true;
            _debounceTimer.Start();

            try
            {
                var content = GetClipboardText();
                if (!string.IsNullOrEmpty(content) && content != _lastContent)
                {
                    _lastContent = content;
                    if (IsValidUrl(content))
                    {
                        UrlDetected?.Invoke(this, content);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine($"Clipboard error: {ex.Message}");
            }
            finally
            {
                _isProcessing = false;
            }
        }
        #endregion

        #region 核心方法
        private string GetClipboardText()
        {
            IDataObject data = null;
            for (var i = 0; i < 3; i++) // 最多重试3次
            {
                try
                {
                    data = Clipboard.GetDataObject();
                    if (data?.GetDataPresent(DataFormats.Text) ?? false)
                    {
                        return data.GetData(DataFormats.Text) as string;
                    }
                    break;
                }
                catch (ExternalException) when (i < 2) // 忽略前两次错误
                {
                    System.Threading.Thread.Sleep(50);
                }
            }
            return null;
        }

        private bool IsValidUrl(string input)
        {
            return _urlRegex.IsMatch(input.Trim());
        }
        #endregion

        #region 释放资源
        private bool _disposed;

        public void Dispose()
        {
            if (_disposed) return;

            _debounceTimer.Dispose();
            _listenerWindow.Dispose(); 
            Stop();

            _disposed = true;
            GC.SuppressFinalize(this);
        }
        #endregion

       

        #region 隐藏窗口实现
        private class ClipboardListenerWindow : NativeWindow
        {
            public event EventHandler ClipboardUpdated;

            public ClipboardListenerWindow()
            {
                CreateHandle(new CreateParams
                {
                    X = CW_USEDEFAULT,
                    Y = CW_USEDEFAULT,
                    Width = 0,
                    Height = 0,
                    Parent = IntPtr.Zero,
                    Style = 0,
                    ExStyle = 0
                });

                SetParent(Handle, IntPtr.Zero); // 分离窗口层级
            }

            protected override void WndProc(ref Message m)
            {
                if (m.Msg == WM_CLIPBOARDUPDATE)
                {
                    ClipboardUpdated?.Invoke(this, EventArgs.Empty);
                }
                base.WndProc(ref m);
            }

            // 添加Dispose实现
            public new void Dispose()
            {
                if (Handle != IntPtr.Zero)
                {
                    DestroyHandle();
                }
                //base.Dispose(true);
            }

            //protected override void Dispose(bool disposing)
            //{
            //    if (disposing)
            //    {
            //        // 释放托管资源
            //    }
            //    base.Dispose(disposing);
            //}
        }
        #endregion
    }
}